<?php
namespace common\models;





use api\modules\v1\controllers\VesController;
use common\models\finance\BalanceTypeModel;
use common\service\vesrpc\ves;
use yii\db\Query;

class Balance extends BaseModel
{
    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return 'balance';
    }

    public static $typeNameEn = array('1' => 'Seeds' ,'3'=> 'Carbon credits');

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['mch_id', 'member_id', 'balance_type', 'create_time', 'update_time'], 'integer'],
            [['balance', 'total_balance', 'use_balance'], 'number'],
            [['balance_type'], 'required'],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'mch_id' => '商户id',
            'member_id' => '会员ID',
            'balance' => '余额',
            'total_balance' => '总金额',
            'balance_type' => '账本类型',
            'use_balance' => '已使用金额',
            'create_time' => '有效开始时间',
            'update_time' => '更新时间',
        ];
    }    

	/*
		* 数据列表
		* whereArr 条件
		* params 基本参数 包含 field order page limit
		* extends  扩展信息 一些相关的信息
		* 
	*/	
	public static function dataList($whereArr, $params, $extends = array())
	{
		$model  = self::find();
		$where  = isset($whereArr['where']) ? $whereArr['where'] : [];
		$whereAnd = isset($whereArr['and'])?$whereArr['and']:[];
		$models = self::queryFormart($model,$where,$params,$whereAnd);
		$model  = $models['model'];
		
		$data  = $model->asarray()->all();
		if(!$data) return array();

		//扩展信息
		if(!$extends) return $data;

		foreach($extends as $extend)
		{

		}

		return $data;	
	}

	public static function getOne($where, $field = ['*'])
	{
		return self::find()->select($field)->where($where)->asarray()->one();
	}


	public static function getAll($where = [], $field = ['*'])
	{
		return self::find()->select($field)->where($where)->asarray()->all();
	}

    /*
  账本类型
*/
    public static function balanceTypeName($type=0)
    {
        $lang = \Yii::$app->params['lang'];

        if($type>0)
        {
            $data =  BalanceType::find()->where(['type'=>$type,'mch_id'=>MCHID])->asarray()->one();
            if($data && $lang == 'en'){
                $data['type_name'] = isset(self::$typeNameEn[$data['type']])?self::$typeNameEn[$data['type']]:$data['type_name'];
            }
            return $data;
        }

        $typeInfo = BalanceType::find()->where(['mch_id'=>MCHID])->asarray()->all();
        $data = array();
        foreach($typeInfo as $val)
        {
            $typeName = $val['type_name'];
            if($lang == 'en') $typeName = isset(self::$typeNameEn[$val['type']])?self::$typeNameEn[$val['type']]:$typeName;
            $data[$val['type']] =  $typeName;
        }
        return $data;
    }


    /*
    *会员帐本列表
    * whereArr 条件
    * params 基本参数 包含 field order page limit
    * extends  扩展信息 一些相关的信息
   */
    public static function balanceList($whereArr,$params,$extends=[])
    {
        $model  = self::find();
        $where  = $whereArr['where'];
        $whereAnd = isset($whereArr['whereAnd'])?$whereArr['whereAnd']:[];
        if (isset($where['member_name']) && $where['member_name']){
           $id_arr = Member::getAll(['like','member_name',$where['member_name']],'member_id,member_name');
           if ($id_arr){
               $idArr = array_column($id_arr,'member_id');

              unset($where['member_name']);
             array_push($idArr,$where['member_id']??'');
             $where['member_id']=$idArr;

           }
        }
        $models = self::queryFormart($model,$where,$params,$whereAnd);
        $model  = $models['model'];
        self::$pages = $models['pages'];

        $data  = $model->asarray()->all();
        if(!$data) return array();

        //账本类型名
        $typeName = self::balanceTypeName();
        foreach($data as &$val)
        {
            $val['type_name'] = isset($typeName[$val['balance_type']])?$typeName[$val['balance_type']]:'undefine';
            foreach($extends as $eType)
            {
                if($eType=='member')
                {
                    $field = ['member_name','member_avatar','member_mobile'];
                    $member = Member::getMemberById($val['member_id'],$field);
                    if($member) $val = array_merge($member,$val);
                }
            }
        }
        return $data;
    }


    /*
    获取帐本余额
    * memberId 会员ID
    * bType 账本类型
    ifIn 类内部 调用
   */
    public static function getBalance($memberId, $bType, $ifIn = false)
    {
        $field = "a.balance,a.id,a.balance_type,a.total_balance,a.use_balance,a.member_id,b.type_name,b.is_tixian,b.is_exchange,b.is_transfer,b.is_recharge,b.price";
        $data = self::find()->alias('a')->select($field)
            ->leftJoin('balance_type as b','a.balance_type=b.type')
            ->where(['a.member_id'=>$memberId,'a.balance_type'=>$bType,'a.mch_id'=>0])
            ->asarray()->one();
        $lang = \Yii::$app->params['lang'];

        if($ifIn) return $data;

        if($data){
            if($lang == 'en') $data['type_name'] = isset(self::$typeNameEn[$data['balance_type']])?self::$typeNameEn[$data['balance_type']]:$data['type_name'];
            $data['is_detail'] = 1;
            return $data;
        }

        ## 给一个默认数据
        $res = BalanceType::find()->where(['type'=>$bType,'mch_id'=>MCHID])->asarray()->one();
        if(!$res) return $data;
        $data = ['member_id'=>$memberId,'type_name'=>$res['type_name'],'balance_type'=>$res['type'],'balance'=>0];
        $data['is_tixian'] = $res['is_tixian'];
        $data['is_exchange'] = $res['is_exchange'];
        $data['is_transfer'] = $res['is_transfer'];
        $data['is_recharge'] = $res['is_recharge'];
        $data['is_detail'] = 1;
        $data['price'] = $res['price'];
        if($data){
            if($lang == 'en') $data['type_name'] = isset(self::$typeNameEn[$data['balance_type']])?self::$typeNameEn[$data['balance_type']]:$data['type_name'];
            return $data;
        }
        return $data;
    }


    /*
    创建一个帐本
   */
    private static function createNewBalance($mid,$btype)
    {
        //有没有创建该帐本类型
        $typeInfo = (new Query)->from('balance_type')->where(["type"=>$btype,'mch_id'=>MCHID])->one();
        if(!$typeInfo) return array("state"=>0,"msg"=>'没有可用帐本');
        $data = array(
            'member_id'         => $mid,
            'mch_id'            => MCHID,
            "balance"           => 0,
            "total_balance"     => 0,
            "balance_type"      => $btype,
            "use_balance"       => 0,
            "update_time"       => time(),
            "create_time"       => time()
        );
        $model = new self;
        if(!$model->load($data,'') || !$model->save())
            return self::outError($model->errors);
        $id = \Yii::$app->db->getLastInsertID();
        $data['id'] = $id;
        $data['type_name'] = $typeInfo['type_name'];
        return array('state'=>1,'msg'=>'创建帐本成功！','cur_balance'=>$data);
    }



    /*
    * 增加账本余额 账本+操作
    * mid       会员id
    * btype  账本类型
    * totalFee  金额
    * sType     操作类型  表balance_log的source_type定义
    * sourceId  与类型对应，对应的日志或订单id
    * from      分红的来源 （比如是来自某个人）
    * reback    是否为驳回增加，默认为否
*/

    public static function addBalance($mid,$btype,$totalFee,$sType='',$sourceId=0,$from='',$reback=false,$is_lock=0,$is_await=0)
    {
        if($totalFee<=0) return array("state"=>false,"msg"=>'金额不能小于0');
        $curBalance = self::getBalance($mid,$btype,true);

        if(!$curBalance)
        {
            $res = self::createNewBalance($mid,$btype);

            if(!$res['state']) return array("state"=>false,"msg"=>$res['msg']);
            $curBalance = $res['cur_balance'];
        }

        $data = array(
            'balance'       => $curBalance['balance'] + $totalFee,
            'total_balance' => $curBalance['total_balance'] + $totalFee,
            'update_time'   => time(),
        );
        //驳回
        if($reback){
            $data['total_balance'] = $curBalance['total_balance'];
            $data['use_balance']   = $curBalance['use_balance'] - $totalFee;
            $data['balance']       = $curBalance['balance'] + $totalFee;
        }
        $where = array("id"=>$curBalance['id']);
        $flag  = self::updateAll($data,$where);
        if(!$flag) return array("state"=>false,"msg"=>'增加帐本失败');

        $note = "+".round($totalFee,4);
        $flag  = self::addBalanceLog($curBalance,$totalFee,$sType,1,$sourceId,$from,$note,$is_lock,$is_await);
        return array("state"=>true,"msg"=>'增加帐本成功');
    }

    /*
       记录日志
   */
    public static function addBalanceLog($curBalance,$totalFee,$sType,$type,$sourceId,$from,$note,$is_lock,$is_await)
    {
        $data = array(
            'member_id'         => $curBalance['member_id'],
            'mch_id'            => 0,
            "balance"           => $totalFee,
            "balance_id"        => $curBalance['id'],
            "balance_type"      => $curBalance['balance_type'],
            "source_type"       => $sType,
            "log_type"          => $type,
            "source_id"         => $sourceId,
            "old_balance"       => $curBalance['balance'],
            "note"              => $note,
            'bonus_from'        => $from,
            "create_time"       => time(),
            "is_lock"           =>$is_lock,
            'is_await'          =>$is_await,
        );
        $model = new BalanceLog();

        return ($model->load($data,'')&&$model->save());
    }


    /*
     * 减少余额 账本-操作
     * mid 会员id
     * typeId   会员类型
     * bType    账本类型
     * money    金额
     * sType    操作类型  表balance_log的source_type定义
     * sourceId 与类型对应，对应的日志或订单id
 */

    public static function transferBalanceToVes($mid, $btype, $totalFee, $sType = '', $sourceId = 0, $from = '',$is_lock=0,$is_await=0)
    {
        if($totalFee<=0) return array("state"=>false,"msg"=>'账本金额不能为空');

        $curBalance =self::getBalance($mid,$btype,true);

        if(!$curBalance)
            return array("state"=>false,"msg"=>'用户余额不足');

        if($curBalance['balance']<$totalFee)
            return array("state"=>false,"msg"=>'用户余额不足');

        $data = array(
            'balance'       => $curBalance['balance'] - $totalFee,
            'use_balance'   => $curBalance['use_balance'] + $totalFee,
            'update_time'   => time(),
        );
        $where = ["id"=>$curBalance['id']];

        $flag  = self::updateAll($data,$where);

        if(!$flag)
            return array("state"=>false,"msg"=>'用户余额扣除失败');
        $note = "-".round($totalFee,4);
        $flag  = self::addBalanceLog($curBalance,$totalFee,$sType,0,$sourceId,$from,$note,$is_lock,$is_await);

        return array("state"=>$flag,'msg'=>'减少账本成功');
    }

    public static function reduceBalance($mid, $btype, $totalFee, $sType = '', $sourceId = 0, $from = '',$is_lock=0,$is_await=0)
    {
        if($totalFee<=0) return array("state"=>false,"msg"=>'账本金额不能为空');

        $symbol = ($btype+0)==2?'UPH':'USDT';
        $curBalance =self::getBalance($mid,$btype,true);
        $vesBalance = 0;
        $data = ves::balance_query($mid, $symbol);
        if($data['error'] == null) {
            $vesBalance = $data['result'][$symbol]['available'];
        }

        \Yii::getLogger()->log('====transferBalanceToVes', 'info');
        \Yii::getLogger()->log(json_encode($curBalance), 'info');
        \Yii::getLogger()->log(json_encode($vesBalance), 'info');
        if(!$curBalance)
            return array("state"=>false,"msg"=>'用户余额不足');

        if($curBalance['balance']+$vesBalance<$totalFee)
            return array("state"=>false,"msg"=>'用户余额不足');

        $deductMoney = $totalFee>$curBalance['balance']?$curBalance['balance']:$totalFee;
        $afterBalance = $curBalance['balance'] - $totalFee;
        $afterBalance = $afterBalance>0?$afterBalance:0;
        $vesDeductMoney = $totalFee-$curBalance['balance'];
        $vesDeductMoney = $vesDeductMoney>0?$vesDeductMoney:0;

        $data = array(
            'balance'       => $afterBalance,
            'use_balance'   => $curBalance['use_balance'] + $deductMoney,
            'update_time'   => time(),
        );
        $where = ["id"=>$curBalance['id']];
        try{
            $transaction = \Yii::$app->db->beginTransaction();
            $flag  = self::updateAll($data,$where);
            if(!$flag)
                throw new \Exception('用户余额扣除失败');
            $note = "-".round($deductMoney,4);
            $flag  = self::addBalanceLog($curBalance,$deductMoney,$sType,0,$sourceId,$from,$note,$is_lock,$is_await);
            $id = \Yii::$app->db->getLastInsertId();
            if($id<1){
                throw new \Exception('用户流水日志插入失败');
            }
            if($vesDeductMoney>0){
                $data = ves::balance_update($mid,$symbol,'兑换',$id,$vesDeductMoney);
                if($data['error'] != null) {
                    throw new \Exception('交易所钱包操作失败');
                }
            }

            $transaction->commit();
            return ['state' => true,'msg' => '减少账本成功'];
        }catch (\Exception $e){
            $transaction->rollback();
            return ['state' => false,'msg' => $e->getMessage()];
        }
        return array("state"=>$flag,'msg'=>'减少账本失败');
    }


    public static function wallet($memberId,$btype){

        /*获取总金额余额*/
        $balance = self::find()->where(['member_id'=>$memberId])->sum('balance');

        $balances = BalanceLog::find()->where("(is_lock=1 or is_await=1) and member_id=$memberId")->sum('balance');
          $data['balance'] = round($balance+$balances,4)??0;

        $instance = StaticInstance::getAll(['member_id'=>$memberId,'status'=>1,'order_type'=>['1','2','3']],'commodity_id,type,in_num,was_num');
      
        $wallet   = self::find()->where(['member_id'=>$memberId,'balance_type'=>1])->sum('balance');
        $data['wallet'] = $wallet+$balances??0;
        /*获取合同本金*/
        $data['instance'] = round(array_sum(array_column($instance,'in_num')),2)??0;

        /*获取总收益*/
         $was_num= Balance::getOne(['member_id'=>$memberId,'balance_type'=>4],'balance');
        $data['was_num']=$was_num['balance'];
        /*总资产*/
        $data['count']  =$data['balance']??0;
        $data['text']   = round($data['count']*7,2);
        /*开始时间*/
        $startTime = strtotime(date('Y-m-d 00:00:00',time()));
        /*今日合约收益*/
        $day_instance = BalanceLog::getAll("source_type in (8,9,17,10) and log_type=1 and create_time>='".$startTime."' and create_time<='".time()."' and member_id=$memberId",'balance');
        $data['day_num'] = round(array_sum(array_column($day_instance,'balance')),2)??0;

        return $data;

    }


    /*
       获取所有帐本余额
       * memberId 会员ID
    */
    public static function getAllBalance($memberId)
    {
        $data = BalanceType::find()->where(['mch_id'=>MCHID])->asarray()->all();
        $list = array();
        foreach($data as $val)
        {
            $bInfo = self::getBalance($memberId,$val['type']);
            $list[] = $bInfo;
        }

        /*获取当前用户锁定余额*/
         $suoding = BalanceLog::find()->where(['member_id'=>$memberId,'is_lock'=>1])->sum('balance');
         $is_await = 0;

         /*判断当前用户中奖的时间点*/
         $winning = GroupWinning::getAll(['member_id'=>$memberId,'is_order'=>2],'winning_time,group_money');
         foreach ($winning as $k=>$v){
             if (time()<strtotime($v['winning_time'])){
                 $suoding+=$v['group_money'];
             }else{
                 $is_await+=$v['group_money'];
             }
         }
         $datas = [
             'is_await'=>$is_await,
             'is_lock' =>$suoding,
             'type_name'=>'钱包管理',
             'balance_type'=>5
         ];
          array_push($list,$datas);
        return $list;
    }

}